package butines.core.gui.style;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.RenderingHints;




public class Text {

    private static final Color DEFAULT_COLOR_1 = new Color(234, 195, 120);
    private static final Color DEFAULT_COLOR_2 = new Color(178, 139, 63);
    
    private Font font;
    private Color color1;
    private Color color2;
    private boolean cyclic;
    private HAlign hAlign;
    private VAlign vAlign;
    
    public Text(Font font, HAlign hAlign, VAlign vAlign, Color color1, Color color2, boolean cyclic) {
        this.font = font;
        this.hAlign = hAlign;
        this.vAlign = vAlign;
        this.color1 = color1;
        this.color2 = color2;
        this.cyclic = cyclic;
    }
        
    public Text(Font font) {
        this(font, HAlign.LEFT, VAlign.TOP, DEFAULT_COLOR_1, DEFAULT_COLOR_2, false);
    }
    
    public Text(Font font, HAlign hAlign) {
    	this(font, hAlign, VAlign.TOP, DEFAULT_COLOR_1, DEFAULT_COLOR_2, false);    	
    }
    
    public Text(Font font, HAlign hAlign, Color color) {
        this(font, hAlign, VAlign.TOP, color, color, false);
    }
    
    private Text() {
        
    }
    
    public Text copy() {
        Text other = new Text();
        other.font = this.font;
        other.hAlign = this.hAlign;
        other.vAlign = this.vAlign;
        other.color1 = this.color1;
        other.color2 = this.color2;
        other.cyclic = this.cyclic;
        return other;
    }
    
    private Paint createGradientPaint(int sy, int height) {
        if (color1.equals(color2)) {
            return color1;
        }
        int hstr = cyclic ? height / 2 : height;
        return new GradientPaint(0, sy, color1, 0, sy + hstr, color2, cyclic);
    }
    
    public Dimension measuring(String str) {
        
        FontMetrics metrics = Fonts.getFontMetrics(font);
        int hline = metrics.getHeight();

        int x1 = 0;
        int y1 = hline;

        int x2 = 0, y2 = 0;

        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (ch == '\n' || ch == '\r') {
                x1 = 0;
                y1 = y1 + hline;
            } else if (ch == '\t') {
                x1 = x1 + metrics.charWidth(' ') * 4;
            } else {
                x1 = x1 + metrics.charWidth(ch);
            }
            x2 = (x1 > x2) ? x1 : x2;
            y2 = (y1 > y2) ? y1 : y2;
        }
        
        return new Dimension(x2, y2);
    }
    
    private int hAlign(int x, int wstr, int wbox) {
    	if (hAlign == HAlign.CENTER) {
    		return x + (wbox - wstr) / 2;
    	} else if (hAlign == HAlign.RIGHT) {
    		return x + (wbox - wstr);
    	} else {
    		return x;
    	}
    }
    
    private int vAlign(int y, int hstr, int hbox) {
        if (vAlign == VAlign.MIDDLE) {
            return y + (hbox - hstr) / 2;
        } else if (vAlign == VAlign.BOTTOM) {
            return y + (hbox - hstr);
        } else {
            return y;
        }
    }
    
    public void draw(Graphics2D g, int sx, int sy, String text) {
        draw(g, sx, sy, text, 0, 0);
    }
    
    public void draw(Graphics2D g, int sx, int sy, String text, int wbox, int hbox) {
        
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setFont(font);

        FontMetrics fm = g2d.getFontMetrics();
        int mdesc = fm.getMaxDescent();
        int hline = fm.getHeight();
        
        StringBuilder line = new StringBuilder();
        Dimension d = measuring(text);
        int x = sx;
        int y = vAlign(sy, d.height, hbox);
        
        for (int i = 0; i < text.length(); i++) {
            char ch = text.charAt(i);
            if (ch == '\n' || ch == '\r') {
            	String str = line.toString();
            	line.setLength(0);
            	g2d.setPaint(createGradientPaint(y, hline));
            	g2d.drawString(str, hAlign(x, d.width, wbox), y + hline - mdesc);
                y += hline;
            } else if (ch == '\t') {
                line.append("    ");
            } else {
                line.append(ch);
            }
        }
        if (!text.isEmpty()) {
        	String str = line.toString();
        	line.setLength(0);
        	g2d.setPaint(createGradientPaint(y, hline));
        	g2d.drawString(str, hAlign(x, d.width, wbox), y + hline - mdesc);
        }
        
        // debug
//        Dimension d = measuring(text);
//        g2d.setColor(Color.blue);
//        g2d.drawRect(sx, sy, wbox, d.height);
//        g2d.setColor(Color.red);
//        g2d.drawRect(hAlign(sx, d.width, wbox), sy, d.width, d.height);
        
        g2d.dispose();
        
    }

    public Font getFont() {
        return font;
    }

    public void setFont(Font font) {
        this.font = font;
    }

    public Color getColor1() {
        return color1;
    }

    public void setColor1(Color color1) {
        this.color1 = color1;
    }

    public Color getColor2() {
        return color2;
    }

    public void setColor2(Color color2) {
        this.color2 = color2;
    }

    public boolean isCyclic() {
        return cyclic;
    }

    public void setCyclic(boolean cyclic) {
        this.cyclic = cyclic;
    }

    public HAlign getHAlign() {
        return hAlign;
    }

    public void setHAlign(HAlign hAlign) {
        this.hAlign = hAlign;
    }

    public VAlign getVAlign() {
        return vAlign;
    }

    public void setVAlign(VAlign vAlign) {
        this.vAlign = vAlign;
    }
    
    public Text setColor(Color color) {
        color1 = color;
        color2 = color;
        return this;
    }

}
